#include "NeoProgressCircle.h"
#include "private/NeoProgressCirclePrivate.h"
#include <QPropertyAnimation>
#include <QResizeEvent>

NEO_PUBLIC_PROPERTY_CREATE_CPP(NeoProgressCircle, QColor, BackgroundColor)
NEO_PUBLIC_PROPERTY_CREATE_CPP(NeoProgressCircle, QColor, ProgressColor)
NEO_PUBLIC_PROPERTY_CREATE_CPP(NeoProgressCircle, bool, ShowText)

NeoProgressCircle::NeoProgressCircle(QWidget *parent)
    : QWidget(parent), d_ptr(new NeoProgressCirclePrivate(this))
{
    NEO_PUBLIC_POINT(NeoProgressCircle)
    d->q_ptr = this;
    connect(d->pPositionAnimation, &QPropertyAnimation::valueChanged, this, [this]()
            { this->update(); });
    connect(d->pPositionAnimation, &QPropertyAnimation::finished, this, [this]()
            {        NEO_PUBLIC_POINT(NeoProgressCircle)
        d->pValue = d->pPositionAnimation->endValue().toInt();
        emit neoValueChanged(); });
}
NeoProgressCircle::~NeoProgressCircle() = default;

void NeoProgressCircle::setValue(int value)
{
    NEO_PUBLIC_POINT(NeoProgressCircle)
    if (value < d->pMinimumValue || value > d->pMaximumValue)
    {
        qWarning() << "Value out of range. Must be between" << d->pMinimumValue << "and" << d->pMaximumValue;
        return;
    }
    else if (value <= d->pValue)
    {
        qWarning() << "Value is already set to" << value << ". No animation needed.";
        return;
    }
    d->startPositionAnimation(value);
}

int NeoProgressCircle::getValue() const
{
    NEO_PUBLIC_POINT(const NeoProgressCircle)
    return d->pValue;
}

void NeoProgressCircle::setMinimumValue(int minimum)
{
    NEO_PUBLIC_POINT(NeoProgressCircle)
    if (minimum > d->pMaximumValue)
    {
        qWarning() << "Minimum value cannot be greater than maximum value.";
        return;
    }
    else if (minimum > d->pValue)
    {
        qWarning() << "Minimum value is greater than current value. Adjusting current value.";
        d->pValue = minimum;
    }
    d->pMinimumValue = minimum;
}

int NeoProgressCircle::getMinimumValue() const
{
    NEO_PUBLIC_POINT(const NeoProgressCircle)
    return d->pMinimumValue;
}

void NeoProgressCircle::setMaximumValue(int maximum)
{
    NEO_PUBLIC_POINT(NeoProgressCircle)
    if (maximum < d->pMinimumValue)
    {
        qWarning() << "Maximum value cannot be less than minimum value.";
        return;
    }
    else if (maximum < d->pValue)
    {
        qWarning() << "Maximum value is less than current value. Adjusting current value.";
        d->pValue = maximum;
    }
    d->pMaximumValue = maximum;
}

int NeoProgressCircle::getMaximumValue() const
{
    NEO_PUBLIC_POINT(const NeoProgressCircle)
    return d->pMaximumValue;
}

void NeoProgressCircle::setProgressPixmap(QPixmap pixmap)
{
    NEO_PUBLIC_POINT(NeoProgressCircle)
    if (pixmap.isNull())
    {
        qWarning() << "Cannot set a null pixmap.";
        return;
    }
    d->pProgressPixmap = pixmap.scaled(this->width(), this->height());
}

QPixmap NeoProgressCircle::getProgressPixmap() const
{
    NEO_PUBLIC_POINT(const NeoProgressCircle)
    return d->pProgressPixmap;
}

void NeoProgressCircle::setRange(int minimum, int maximum)
{
    setMinimumValue(minimum);
    setMaximumValue(maximum);
}

void NeoProgressCircle::resizeEvent(QResizeEvent *event)
{
    NEO_PUBLIC_POINT(NeoProgressCircle)
    d->updateWidgetGeometry(event->size());
    return QWidget::resizeEvent(event);
}

void NeoProgressCircle::paintEvent(QPaintEvent *event)
{
    NEO_PUBLIC_POINT(NeoProgressCircle)
    NEO_PAINTER_RESET
    d->drawBackground(&painter);
    d->drawProgress(&painter);
    d->drawText(&painter);
}
